﻿var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var RestKit;
(function (_RestKit) {
    

    

    

    

    

    

    /** A very simple promise provider */
    var VerySimplePromise = (function () {
        function VerySimplePromise() {
            this._fulfilled = [];
            this._rejected = [];
            this.promise = this;
        }
        VerySimplePromise.prototype.execute = function (list, args) {
            var i = list.length;

            // convert arguments to an array
            // so they can be sent to the
            // callbacks via the apply method
            args = Array.prototype.slice.call(args);

            while (i--)
                list[i].apply(null, args);
        };
        VerySimplePromise.prototype.then = function (fulfilled, rejected) {
            if (fulfilled != null)
                this._fulfilled.push(fulfilled);
            if (rejected != null)
                this._rejected.push(rejected);

            return this;
        };

        VerySimplePromise.prototype.done = function (func) {
            this._fulfilled.push(func);
            return this;
        };
        VerySimplePromise.prototype.fail = function (func) {
            this._rejected.push(func);
            return this;
        };
        VerySimplePromise.prototype.always = function (func) {
            this._fulfilled.push(func);
            this._rejected.push(func);
            return this;
        };
        VerySimplePromise.prototype.reject = function (reason) {
            this.execute(this._rejected, arguments);
        };

        VerySimplePromise.prototype.resolve = function (value) {
            this.execute(this._fulfilled, arguments);
        };
        VerySimplePromise.prototype.notify = function (message) {
        };
        return VerySimplePromise;
    })();
    _RestKit.VerySimplePromise = VerySimplePromise;

    /** The restkit it self */
    var RestKit = (function () {
        /** Create a new RestKit with dependencies
        * @constructor
        * @param {delegate} defer - Method used to instaniate the promise
        * @param {delegate} [xhrProvider] - Method used to instantiate the Http Request Object.
        * @param {delegate} [contextProvider] - Method used to get the Xrm context object.
        */
        function RestKit(defer, xhrProvider, contextProvider) {
            if (typeof xhrProvider === "undefined") { xhrProvider = RestKit.getXhrInstance; }
            if (typeof contextProvider === "undefined") { contextProvider = RestKit.getContext; }
            /**
            * @const
            */
            this.ODATA_ENDPOINT = '/XRMServices/2011/OrganizationData.svc';
            this.oDataPathCache = null;
            this._deferFactory = defer;
            this._xhrProvider = xhrProvider;
            this._contextProvider = contextProvider;
        }
        /** Retrieve a record
        * @param {string} entityName Schema name of the entity
        * @param {string} id Id of the record to retrieve
        * @param {string[]} columns list of columns
        * @param {boolean} [async=true] Execute asynchrously
        */
        RestKit.prototype.Retrieve = function (entityName, id, columns, async) {
            if (typeof async === "undefined") { async = true; }
            var url = this.getODataPath() + "/" + entityName + "Set(guid'" + id + "')" + "?$select=" + columns.join(',');

            return this.ajax('GET', url, async);
        };

        /** Create a record
        * @param {string} entityName Schema name of the entity
        * @param {TEntity} entityObject The entity to be created
        * @param {boolean} [async=true] Execute asynchrously
        */
        RestKit.prototype.Create = function (entityName, entityObject, async) {
            if (typeof async === "undefined") { async = true; }
            // default is 'true'
            var setName = entityName + 'Set', data = JSON.stringify(entityObject), url = this.getODataPath() + "/" + setName;

            // returns a promise object
            return this.ajax('POST', url, async, data);
        };

        /** Update a record
        * @param {string} entityName Schema name of the entity
        * @param {string} id Id of the record to update
        * @param {TEntity} entityObject The entity to be updated
        * @param {boolean} [async=true] Execute asynchrously
        */
        RestKit.prototype.Update = function (entityName, id, entityObject, async) {
            if (typeof async === "undefined") { async = true; }
            var setName = entityName + 'Set', url = this.getODataPath() + "/" + setName + "(guid'" + id + "')", data = JSON.stringify(entityObject), headers = {
                'X-HTTP-Method': 'MERGE'
            };

            // MERGE methode does not return data
            return this.ajax('POST', url, async, data, headers);
        };

        /** Delete a record
        * @param {string} entityName Schema name of the entity
        * @param {string} id Id of the record to delete
        * @param {boolean} [async=true] Execute asynchrously
        */
        RestKit.prototype.Delete = function (entityName, id, async) {
            if (typeof async === "undefined") { async = true; }
            var setName = entityName + 'Set', url = this.getODataPath() + '/' + setName + "(guid'" + id + "')", headers = {
                'X-HTTP-Method': 'DELETE'
            };

            return this.ajax('POST', url, async, null, headers);
        };

        /** Associate two records using a M:N relation
        * @param {string} entity1Id Id of record 1
        * @param {string} entity1Name Schema name of entity 1
        * @param {string} entity2Id Id of record 2
        * @param {string} entity2Name Schema name of entity 2
        * @param {string} relationshipName Schema name of the relation
        * @param {boolean} [async=true] Execute asynchrously
        */
        RestKit.prototype.Associate = function (entity1Id, entity1Name, entity2Id, entity2Name, relationshipName, async) {
            if (typeof async === "undefined") { async = true; }
            var odatapath = this.getODataPath(), url = odatapath + "/" + entity1Name + "Set(guid'" + entity1Id + "')/$links/" + relationshipName, data = JSON.stringify({
                uri: odatapath + "/" + entity2Name + "Set(guid'" + entity2Id + "')"
            });

            return this.ajax('POST', url, async, data);
        };

        /** Disassociate two records from a M:N relation
        * @param {string} entity1Id Id of record 1
        * @param {string} entity1Name Schema name of entity 1
        * @param {string} entity2Id Id of record 2
        * @param {string} relationshipName Schema name of the relation
        * @param {boolean} [async=true] Execute asynchrously
        */
        RestKit.prototype.Disassociate = function (entity1Id, entity1Name, entity2Id, relationshipName, async) {
            if (typeof async === "undefined") { async = true; }
            var url = this.getODataPath() + "/" + entity1Name + "Set(guid'" + entity1Id + "')/$links/" + relationshipName + "(guid'" + entity2Id + "')", headers = {
                'X-HTTP-Method': 'DELETE'
            };

            return this.ajax('POST', url, async, headers);
        };

        /** Retrieve records based on the filter
        * @param {string} entityName Schema name of the entity
        * @param {string[]} columns Schema names of attributes to retrieve
        * @param {string} filter Filter
        * @param {boolean} [async=true] Execute asynchrously
        */
        RestKit.prototype.ByQuery = function (entityName, columns, filter, async) {
            if (typeof async === "undefined") { async = true; }
            // default is 'true'
            var setName = entityName + 'Set', url = null;

            // in case filter is empty
            filter = (filter) ? "&$filter=" + encodeURIComponent(filter) : '';
            url = this.getODataPath() + "/" + setName + "?$select=" + columns.join(',') + filter;

            return this.ajax('GET', url, async);
        };

        /** Retrieve records based on a full ODATA url string. Mainly used to page results.
        * @param {string} queryUrl The query string
        * @param {boolean} [async=true] Execute asynchrously
        */
        RestKit.prototype.ByQueryUrl = function (queryUrl, async) {
            if (typeof async === "undefined") { async = true; }
            return this.ajax('GET', queryUrl, async);
        };

        /** Retrieve records based on the filter including related entities
        * @param {string} entityName Schema name of the entity
        * @param {string[]} columns Schema names of attributes to retrieve
        * @param {string} expand Relations to expand
        * @param {string} filter Filter
        * @param {boolean} [async=true] Execute asynchrously
        */
        RestKit.prototype.ByExpandQuery = function (entityName, columns, expand, filter, async) {
            if (typeof async === "undefined") { async = true; }
            var setName = entityName + 'Set', url = null;

            // in case filter is empty
            filter = (filter) ? "&$filter=" + encodeURIComponent(filter) : '';

            url = this.getODataPath() + "/" + setName + "?$select=" + columns.join(',') + '&$expand=' + expand + filter;

            return this.ajax('GET', url, async);
        };

        /** Retrieve all pages of the records based on the filter
        * @param {string} entityName Schema name of the entity
        * @param {string[]} columns Schema names of attributes to retrieve
        * @param {string} filter Filter
        * @param {boolean} [async=true] Execute asynchrously
        */
        RestKit.prototype.ByQueryAll = function (entityName, columns, filter, async) {
            if (typeof async === "undefined") { async = true; }
            var self = this, dfdAll = this._deferFactory(), allRecords = [];

            this.ByQuery(entityName, columns, filter, async).then(function byQueryAllSuccess(result) {
                // add the elements to the collection
                allRecords = allRecords.concat(result.d.results);

                if (result.d.__next) {
                    // the success-handler will be this function
                    self.ByQueryUrl(result.d.__next, async).then(byQueryAllSuccess, dfdAll.reject);

                    // call the progressCallbacks of the promise
                    dfdAll.notify(result);
                } else {
                    dfdAll.resolve(allRecords);
                }
            }, dfdAll.reject);

            return dfdAll.promise;
        };

        //#region Server Url
        /**
        * Default method used to get the Xrm Context. This automatically uses Xrm.Page.context
        * or GetGlobalContext.
        */
        RestKit.getContext = function () {
            if (typeof Xrm !== 'undefined') {
                return Xrm.Page.context;
            } else if (typeof GetGlobalContext !== 'undefined') {
                /*ignore jslint start*/
                return GetGlobalContext();
                /*ignore jslint end*/
            } else {
                throw new Error("Context is not available.");
            }
        };

        /**
        * Returns the server-url based on the current dynamics crm version
        */
        RestKit.prototype.getServerUrl = function () {
            var localServerUrl = window.location.protocol + '//' + window.location.host;
            var context = this._contextProvider();

            if (typeof context.getClientUrl == 'function') {
                // since version SDK 5.0.13
                // http://www.magnetismsolutions.com/blog/gayan-pereras-blog/2013/01/07/crm-2011-polaris-new-xrm.page-method
                return Xrm.Page.context.getClientUrl();
            } else if (context.isOutlookClient() && !context.isOutlookOnline()) {
                return localServerUrl;
            } else {
                var url = context.getServerUrl();
                url = url.replace(/^(http|https):\/\/([_a-zA-Z0-9\-\.]+)(:([0-9]{1,5}))?/, localServerUrl);
                url = url.replace(/\/$/, "");

                return url;
            }
        };

        /**
        * Returns the joined server-url and the endpoint-url
        */
        RestKit.prototype.getODataPath = function () {
            if (this.oDataPathCache == null) {
                this.oDataPathCache = this.getServerUrl() + this.ODATA_ENDPOINT;
            }

            return this.oDataPathCache;
        };

        //#endregion
        RestKit.getXhrInstance = function () {
            var xhr;

            if (window.XMLHttpRequest) {
                xhr = new XMLHttpRequest();
            } else if (window.ActiveXObject) {
                try  {
                    xhr = new ActiveXObject('Msxml2.XMLHTTP');
                } catch (e) {
                    xhr = new ActiveXObject('Microsoft.XMLHTTP');
                }
            }
            return xhr;
        };

        /**
        * Returns all properties of the parameter as key/value pairs in a queryString.
        * @param {any} data Object to use the parameters from.
        */
        RestKit.prototype.encode = function (data) {
            var result = '';

            if (typeof data === 'string') {
                result = data;
            } else {
                var e = encodeURIComponent;

                for (var key in data) {
                    if (data.hasOwnProperty(key)) {
                        result += '&' + e(key) + '=' + e(data[key]);
                    }
                }
            }
            return result;
        };

        /**
        * Internal method to perform the actual service call
        */
        RestKit.prototype.ajax = function (method, url, async, data, headers) {
            if (typeof async === "undefined") { async = true; }
            if (typeof data === "undefined") { data = {}; }
            if (typeof headers === "undefined") { headers = {}; }
            var deferred = this._deferFactory();

            var xhr;
            var payload = this.encode(data);

            try  {
                xhr = this._xhrProvider();
            } catch (e) {
                deferred.reject(e);
                return;
            }

            if (method === 'GET' && payload) {
                url += '?' + payload;
                payload = null;
            }

            xhr.open(method, url, async);
            xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
            xhr.setRequestHeader('Accept', 'application/json');

            for (var h in headers) {
                if (headers.hasOwnProperty(h)) {
                    xhr.setRequestHeader(h, headers[h]);
                }
            }

            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    var error = (!xhr.status || (xhr.status < 200 || xhr.status >= 300) && xhr.status !== 304);

                    if (error) {
                        deferred.reject(JSON.parse(xhr.responseText));
                    } else {
                        deferred.resolve(JSON.parse(xhr.responseText));
                    }
                }
            };

            xhr.send(payload);

            return deferred.promise;
        };
        return RestKit;
    })();
    _RestKit.RestKit = RestKit;

    //TBD provide typed versions?
    /**
    *  RestKit with typed results using JQuery Defer
    */
    var RestKitJQuery = (function (_super) {
        __extends(RestKitJQuery, _super);
        function RestKitJQuery() {
            _super.apply(this, arguments);
        }
        RestKitJQuery.prototype.Retrieve = function (entityName, id, columns, opt_asyn) {
            if (typeof opt_asyn === "undefined") { opt_asyn = true; }
            return _super.prototype.Retrieve.call(this, entityName, id, columns, opt_asyn);
        };
        return RestKitJQuery;
    })(RestKit);
    _RestKit.RestKitJQuery = RestKitJQuery;

    /** create a new RestKit using JQuery as the promise provider */
    function createJQuery($) {
        return new RestKitJQuery(function () {
            return new JQueryDeferAdaptor(($).Deferred());
        });
    }
    _RestKit.createJQuery = createJQuery;

    /** create a new RestKit using Q as the promise provider */
    function createQ() {
        return new RestKit(function () {
            return Q.defer();
        });
    }
    _RestKit.createQ = createQ;

    /** Create a new RestKit using any promise provider */
    function createOther(createDefer) {
        return new RestKit(createDefer);
    }
    _RestKit.createOther = createOther;

    /** Create a new RestKit using Bluebird as the promise provider */
    function createBlueBird(xhr) {
        return new RestKit(function () {
            return new BlueBirdAdaptor(Promise.defer());
        }, xhr);
    }
    _RestKit.createBlueBird = createBlueBird;

    /** Use the first available promise provider (BlueBird, Q, JQuery, VerySimple)*/
    function create() {
        if (typeof Promise != 'undefined')
            return createBlueBird();
        else if (typeof Q != 'undefined' && Q.defer)
            return createQ();
        else if (typeof jQuery != 'undefined')
            return createJQuery(jQuery);
        else
            return createOther(function () {
                return new VerySimplePromise();
            });

        throw new Error('No promise provider available');
    }
    _RestKit.create = create;

    /** Maps notify to progress  */
    var BlueBirdAdaptor = (function () {
        function BlueBirdAdaptor(defer) {
            this.defer = defer;
            this.promise = defer.promise;
        }
        BlueBirdAdaptor.prototype.reject = function (reason) {
            this.defer.reject(reason);
        };
        BlueBirdAdaptor.prototype.resolve = function (reason) {
            this.defer.resolve(reason);
        };
        BlueBirdAdaptor.prototype.notify = function (message) {
            this.defer.progress(message);
        };
        return BlueBirdAdaptor;
    })();
    _RestKit.BlueBirdAdaptor = BlueBirdAdaptor;

    /** Add the promise property */
    var JQueryDeferAdaptor = (function () {
        function JQueryDeferAdaptor(defer) {
            this.defer = defer;
            this.promise = defer;
        }
        JQueryDeferAdaptor.prototype.reject = function (reason) {
            return new JQueryDeferAdaptor(this.defer.reject(reason));
        };
        JQueryDeferAdaptor.prototype.resolve = function (reason) {
            return new JQueryDeferAdaptor(this.defer.resolve(reason));
        };
        JQueryDeferAdaptor.prototype.notify = function (message) {
            this.defer.notify(message);
        };
        return JQueryDeferAdaptor;
    })();
    _RestKit.JQueryDeferAdaptor = JQueryDeferAdaptor;
})(RestKit || (RestKit = {}));

if (typeof Xrm !== 'undefined')
    var CrmRestKit = RestKit.create();
//# sourceMappingURL=C:/Users/live_000/Source/Workspaces/CrmRestKit/Output/scripts/3.x/TypeScript/CrmRestKit.js.map

